package com.polidea.rxohosble2.sample.example3_discovery;

import com.polidea.rxohosble2.sample.ResourceTable;
import com.polidea.rxohosble2.RxBleConnection;
import com.polidea.rxohosble2.RxBleDevice;
import com.polidea.rxohosble2.sample.DeviceAbility;
import com.polidea.rxohosble2.sample.SampleApplication;
import com.polidea.rxohosble2.sample.example4_characteristic.CharacteristicOperationExampleAbility;
import com.polidea.rxohosble2.sample.util.Utils;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.ohos.schedulers.OhosSchedulers;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.ListContainer;
import ohos.agp.components.Text;

public class ServiceDiscoveryExampleAbility extends Ability {

    Text title;
    Button connectButton;
    ListContainer recyclerView;
    private DiscoveryResultsAdapter adapter;
    private RxBleDevice bleDevice;
    private String macAddress;
    private final CompositeDisposable servicesDisposable = new CompositeDisposable();

    public void onConnectToggleClick(Component component) {
        final Disposable disposable = bleDevice.establishConnection(false)
                .flatMapSingle(RxBleConnection::discoverServices)
                .take(1) // Disconnect automatically after discovery
                .observeOn(OhosSchedulers.mainThread())
                .doFinally(this::updateUI)
                .subscribe(adapter::swapScanResult, this::onConnectionFailure);
        servicesDisposable.add(disposable);

        updateUI();
    }

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        setPattern(ResourceTable.Pattern_base);
        super.setUIContent(ResourceTable.Layout_ability_example3);
        connectButton = (Button)findComponentById(ResourceTable.Id_connect);
        recyclerView = (ListContainer) findComponentById(ResourceTable.Id_scan_results);
        macAddress = intent.getStringParam(DeviceAbility.EXTRA_MAC_ADDRESS);
        //noinspection ConstantConditions
        ((Text) findComponentById(ResourceTable.Id_title)).setText(getString(ResourceTable.String_mac_address, macAddress));
        connectButton.setClickedListener(this::onConnectToggleClick);
        bleDevice = SampleApplication.getRxBleClient(this).getBleDevice(macAddress);
        configureResultList();
    }

    private void configureResultList() {
        adapter = new DiscoveryResultsAdapter(i->{
            final DiscoveryResultsAdapter.AdapterItem itemAtPosition = (DiscoveryResultsAdapter.AdapterItem)adapter.getItem(i);
            onAdapterItemClick(itemAtPosition);
        });
        recyclerView.setItemProvider(adapter);
       /* recyclerView.setItemClickedListener((listContainer, component, i, l) -> {
            final DiscoveryResultsAdapter.AdapterItem itemAtPosition = (DiscoveryResultsAdapter.AdapterItem)adapter.getItem(i);
            onAdapterItemClick(itemAtPosition);
        });*/
    }

    private void onAdapterItemClick(DiscoveryResultsAdapter.AdapterItem item) {
        if (item.type == DiscoveryResultsAdapter.AdapterItem.CHARACTERISTIC) {
            final Intent intent = CharacteristicOperationExampleAbility.startActivityIntent(this, macAddress, item.uuid);
//            If you want to check the alternative advanced implementation comment out the line above and uncomment one below
//            final Intent intent = AdvancedCharacteristicOperationExampleActivity.startActivityIntent(this, macAddress, item.uuid);
            startAbility(intent);
        } else {
            //noinspection ConstantConditions
            Utils.showToast(this, getString(ResourceTable.String_not_clickable));
        }
    }

    private boolean isConnected() {
        return bleDevice.getConnectionState() == RxBleConnection.RxBleConnectionState.CONNECTED;
    }

    private void onConnectionFailure(Throwable throwable) {
        //noinspection ConstantConditions
        Utils.showToast(this, "Connection error: " + throwable);
    }

    private void updateUI() {
        connectButton.setEnabled(!isConnected());
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        servicesDisposable.clear();
    }
}
